<template>
  <v-app>
    <v-navigation-drawer v-model="configsShow" absolute left temporary width="300" :color="color_light"
      style="user-select: none;">
      <v-virtual-scroll bench=10 :items="configsListShow" item-height="42">
        <v-list-item dense>
          <div class="black--text">
            软件信息
          </div>
        </v-list-item>
        <v-divider></v-divider>
        <v-list-item dense>
          <v-list-item-subtitle>
            当前版本
          </v-list-item-subtitle>
          <v-btn text x-small :color="color" @click="open_url_version">v1.0.0</v-btn>
        </v-list-item>
        <v-divider></v-divider>
        <v-list-item dense>
          <v-list-item-subtitle>
            软件帮助
          </v-list-item-subtitle>
          <v-btn text x-small :color="color" @click="open_url_document">documents</v-btn>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <div class="black--text">
            显示设置
          </div>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            数据时间戳
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.timestamp" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">否</v-btn>
            <v-btn depressed x-small class="ma-1">是</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            数据来源
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.dataSource" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">否</v-btn>
            <v-btn depressed x-small class="ma-1">是</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            数据格式
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.dataFormat" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">否</v-btn>
            <v-btn depressed x-small class="ma-1">是</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            接收数据主格式
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.rXMain" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">NONE</v-btn>
            <v-btn depressed x-small class="ma-1">ASCII</v-btn>
            <v-btn depressed x-small class="ma-1">HEX</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            接收数据辅格式
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.rXSupport" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">NONE</v-btn>
            <v-btn depressed x-small class="ma-1">ASCII</v-btn>
            <v-btn depressed x-small class="ma-1">HEX</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            发送数据主格式
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.tXMain" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">NONE</v-btn>
            <v-btn depressed x-small class="ma-1">ASCII</v-btn>
            <v-btn depressed x-small class="ma-1">HEX</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            发送数据辅格式
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.tXSupport" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">NONE</v-btn>
            <v-btn depressed x-small class="ma-1">ASCII</v-btn>
            <v-btn depressed x-small class="ma-1">HEX</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <div class="black--text">
            其他设置
          </div>
        </v-list-item>
        <v-divider></v-divider>

        <v-list-item dense>
          <v-list-item-subtitle>
            中文字体编码
          </v-list-item-subtitle>
          <v-btn-toggle v-model="softwareConfigsList.textEncode" dense tile :color="color" group mandatory>
            <v-btn depressed x-small class="ma-1">GBK</v-btn>
            <v-btn depressed x-small class="ma-1">UTF</v-btn>
          </v-btn-toggle>
        </v-list-item>
        <v-divider></v-divider>
      </v-virtual-scroll>
    </v-navigation-drawer>

    <v-navigation-drawer absolute permanent left mini-variant mini-variant-width="56" class="drag-part">
      <v-list dense class="no-drag-part" style="height : calc(100% - 56px) ;">
        <v-list-item-group v-model="navBarIndex" :color="color" mandatory>
          <v-list-item v-for="(item, i) in navBarItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
      <v-list dense class="no-drag-part" style="height:56px ;">
        <v-list-item>
          <v-list-item-icon @click="configsShow = !configsShow">
            <v-icon>mdi-menu</v-icon>
          </v-list-item-icon>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>

    <v-main app id="editor-box-part" style="height: 100%; width: 100%; padding: 0px 0px 0px 56px;">
      <rs-panes split-to="columns" :allow-resize="true" class="panes-wrap" :size="220" :min-size="220" :max-size="660"
        resizerColor="#e0e0e0" :resizerThickness="1" :resizerBorderColor="color" :resizerBorderThickness="2"
        style="z-index: 0;padding: 0; margin:0;">
        <div slot="secondPane" style="height: 100%; width: 100%;">
          <rs-panes split-to="rows" :allow-resize="true" class="panes-wrap" units='percents' primary="second"
            :size="menuPercent" :min-size="30" :max-size="80" resizerColor="#e0e0e0" :resizerThickness="1"
            :resizerBorderColor="color" :resizerBorderThickness="2" style="z-index: 0;height: 100%; width: 100%;">
            <div slot="firstPane" style="height: 100%; width: 100%; ">
              <v-toolbar dense class="drag-part ml-1 mr-1" height="32" elevation="0">
                <v-btn class="no-drag-part" plain x-small icon @click="btn_menu_set_clicked(0)" tabindex="-1"
                  width="20">
                  <v-icon>mdi-send</v-icon>
                </v-btn>
                <v-btn class="no-drag-part" plain x-small icon @click="btn_menu_set_clicked(1)" tabindex="-1"
                  width="20">
                  <v-icon>mdi-chart-histogram</v-icon>
                </v-btn>
                <!-- <v-btn class="no-drag-part" plain x-small icon @click="btn_editor_saved_clicked" tabindex="-1"
                  width="20">
                  <v-icon>mdi-floppy</v-icon>
                </v-btn> -->
                <v-btn class="no-drag-part" plain x-small icon @click="btn_editor_clear_clicked" tabindex="-1"
                  width="20">
                  <v-icon>mdi-delete</v-icon>
                </v-btn>
                <v-btn class="no-drag-part" plain x-small tabindex="-1" v-for="i in txChannelList.length-1" :key="i"
                  @click="btn_tx_channel_close_clicked(txChannelList[i])">
                  {{txChannelList[i]}}
                </v-btn>
                <v-spacer></v-spacer>
                <v-btn class="no-drag-part" plain x-small icon @click="btn_win_min_clicked" tabindex="-1" width="20">
                  <v-icon>mdi-window-minimize</v-icon>
                </v-btn>
                <v-btn class="no-drag-part" plain x-small icon @click="btn_win_max_clicked" tabindex="-1" width="20">
                  <v-icon>mdi-window-maximize</v-icon>
                </v-btn>
                <v-btn class="no-drag-part" plain x-small icon @click="btn_win_exit_clicked" tabindex="-1" width="20">
                  <v-icon>mdi-window-close</v-icon>
                </v-btn>
              </v-toolbar>

              <!-- RX BOX  -->
              <div id="editor" style="height : calc(100% - 50px - 32px) ; width: 100%;">
              </div>

              <!-- Tx BOX -->
              <v-text-field dense counter="" spellcheck="false" :color="color" v-model="txMessage" class="ml-4 mr-4"
                @keyup.enter.native="btn_tx_send_clicked"
                :hint="`current send format is [${softwareConfigsList.txFormat}] and will auto add [${softwareConfigsList.txAppend}] at end`">
                <template v-slot:prepend-inner>
                  <v-btn depressed x-small class="mt-1 mb-1" @click="btn_tx_format_clicked" width="36">
                    {{softwareConfigsList.txFormat}}
                  </v-btn>
                  <v-btn depressed x-small class="ma-1" @click="btn_tx_channel_clicked" width="52">
                    {{txChannel}}
                  </v-btn>
                </template>
                <template v-slot:append>
                  <v-btn depressed x-small class="ma-1" @click="btn_tx_append_clicked" width="72">
                    {{softwareConfigsList.txAppend}}
                    <v-icon :color="color" right>mdi-link</v-icon>
                  </v-btn>
                  <v-btn depressed x-small class="mt-1 mb-1" @click="btn_tx_send_clicked" width="72">
                    send
                    <v-icon :color="color" right>mdi-send</v-icon>
                  </v-btn>
                </template>
              </v-text-field>
            </div>
            <div slot="secondPane" style="height: 100%; width: 100%;">
              <v-sheet style="height: 100%; width: 100%; user-select: none;">
                <v-virtual-scroll v-show="menuIndex==0" bench=10 :items="txList" item-height="42">
                  <template v-slot:default="{ item }">
                    <v-list-item dense>
                      <v-text-field dense spellcheck="false" :color="color" v-model="item.message" class="ml-0 mr-0"
                        hide-details>
                        <template v-slot:prepend-inner>
                          <v-btn depressed x-small class="mt-1 mb-1" @click="btn_tx_list_format_clicked(item)"
                            width="36">
                            {{ item.format }}
                          </v-btn>
                          <v-btn depressed x-small class="ma-1" @click="btn_tx_list_channel_clicked(item)" width="52">
                            {{ item.channel }}
                          </v-btn>
                        </template>

                        <template v-slot:append>
                          <v-btn depressed x-small class="ma-1" @click="btn_tx_list_append_clicked(item)" width="72">
                            {{ item.append }} <v-icon :color="color" right>mdi-link</v-icon>
                          </v-btn>
                          <v-btn depressed x-small class="mt-1 mb-1" @click="btn_tx_list_send_clicked(item)" width="72">
                            send <v-icon :color="color" right>mdi-send</v-icon>
                          </v-btn>
                        </template>
                      </v-text-field>
                    </v-list-item>
                  </template>
                </v-virtual-scroll>
                <v-card v-show="menuIndex==1" flat tile :color="color_light" height="100%">
                  <v-card v-show="menuShow" flat tile no-gutters style="position: absolute;z-index: 999;">
                    <v-btn icon x-small class="ml-1" @click="btn_chart_start_clicked">
                      <v-icon color="grey lighten-1">{{ chartsStart ? ' mdi-stop' : 'mdi-play' }}</v-icon>
                    </v-btn>
                    <v-btn icon x-small class="ml-1" @click="btn_chart_pause_clicked">
                      <v-icon color="grey lighten-1">{{ chartsPause ? 'mdi-sync' : 'mdi-pause' }}</v-icon>
                    </v-btn>
                    <v-btn icon x-small class="ml-1" @click="btn_chart_clear_clicked">
                      <v-icon color="grey lighten-1">mdi-delete</v-icon>
                    </v-btn>
                  </v-card>
                  <div id="chart" style="height:100%; weight:100%; padding: 0px; margin: 0px;"></div>
                </v-card>

              </v-sheet>
            </div>
          </rs-panes>
        </div>
        <div slot="firstPane" style="height: 100%;user-select: none;">
          <v-card no-gutters height="100%" width="100%" elevation="0">
            <v-toolbar dense class="drag-part" height="16px" elevation="0">
            </v-toolbar>
            <v-sheet style="height: calc(100% - 16px);user-select: none;">
              <v-virtual-scroll v-show="navBarIndex==0" bench=10 :items="comConnectList" item-height="270">
                <template v-slot:default="{ item }">
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      通道名称:{{ item.path }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      描述:{{item.name}}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      波特率:{{ item.buadrate }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      数据位:{{ item.databits }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      停止位:{{ item.stopbits }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      校验位:{{ item.checkBits }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      流控位:{{ item.controlBits }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      接收超时:{{ item.timeOut }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-btn depressed x-small class="ma-1" width="52">
                      {{ item.path }}
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_com_connect_edit_clicked(item)" width="72">
                      EDIT<v-icon :color="color" right>mdi-pencil</v-icon>
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_com_connect_state_clicked(item)" width="72">
                      {{ item.status ? 'CLOSE' : 'START' }}
                      <v-icon :color="item.status ? 'red':color" right>
                        {{ item.status ? 'mdi-stop' : 'mdi-play' }}
                      </v-icon>
                    </v-btn>
                  </v-row>
                  <v-divider></v-divider>
                </template>
              </v-virtual-scroll>

              <v-virtual-scroll v-show="navBarIndex==1" bench=10 :items="netConnectList" item-height="180">
                <template v-slot:default="{ item }">
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      通道名称:{{ item.name }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      网络协议:{{ item.type }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      本地端口:{{ item.localPort }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      远程地址:{{ item.remoteAddr }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      远程端口:{{item.remotePort }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-btn depressed x-small class="ma-1" width="52">
                      {{ item.name }}
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_net_connect_edit_clicked(item)" width="72">
                      EDIT <v-icon :color="color" right>mdi-pencil</v-icon>
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_net_connect_state_clicked(item)" width="72">
                      {{ item.status ? 'CLOSE' : 'START' }}
                      <v-icon :color="item.status ? 'red':color" right>
                        {{ item.status ? 'mdi-stop' : 'mdi-play' }}
                      </v-icon>
                    </v-btn>
                  </v-row>
                  <v-divider></v-divider>
                </template>
              </v-virtual-scroll>

              <v-virtual-scroll v-show="navBarIndex==2" bench=10 :items="quickCmdList" item-height="90">
                <template v-slot:default="{ item }">
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      格式:{{ item.format }} 重复:{{ item.count }} 名称:{{ item.name }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      数据:{{item.message }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-btn depressed x-small class="ma-1" @click="btn_quick_cmd_channel_clicked(item)" width="52">
                      {{ item.channel }}
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_quick_cmd_edit_clicked(item)" width="72">
                      EDIT <v-icon :color="color" right>mdi-pencil</v-icon>
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_quick_cmd_send_clicked(item)" width="72">
                      {{ item.status ? 'STOP' : 'SEND' }}
                      <v-icon :color="item.status ? 'red':color" right>
                        {{ item.status ? 'mdi-stop' : 'mdi-play' }}
                      </v-icon>
                    </v-btn>
                  </v-row>
                  <v-divider></v-divider>
                </template>
              </v-virtual-scroll>

              <v-virtual-scroll v-show="navBarIndex==3" bench=10 :items="historyList" item-height="60">
                <template v-slot:default="{ item }">
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      格式:{{ item.format }} 数据:{{ item.message }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-btn depressed x-small class="ma-1" @click="btn_history_channel_clicked(item)" width="52">
                      {{ item.channel }}
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_history_delete_clicked(item)" width="72">
                      DELETE <v-icon :color="color" right>mdi-delete</v-icon>
                    </v-btn>
                    <v-btn depressed x-small class="ma-1" @click="btn_history_send_clicked(item)" width="72">
                      RESEND <v-icon :color="color" right>mdi-send</v-icon>
                    </v-btn>
                  </v-row>
                  <v-divider></v-divider>
                </template>
              </v-virtual-scroll>

              <v-virtual-scroll v-show="navBarIndex==4" bench=10 :items="retransmitList" item-height="90">
                <template v-slot:default="{ item }">
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      来源通道:{{ item.source }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-list-item-subtitle class="ma-1 text-caption font-weight-regular">
                      转发通道:{{ item.destin }}
                    </v-list-item-subtitle>
                  </v-row>
                  <v-row no-gutters>
                    <v-btn depressed x-small class="ma-1" @click="btn_retransmit_edit_clicked(item)" width="72">
                      EDIT<v-icon :color="color" right>mdi-pencil</v-icon>
                    </v-btn>
                    <v-btn depressed x-small @click="item.status = !item.status" class="ma-1" width="72">
                      {{ item.status ? 'CLOSE' : 'START' }}
                      <v-icon :color="item.status ? 'red':color" right>
                        {{ item.status ? 'mdi-stop' : 'mdi-play' }}
                      </v-icon>
                    </v-btn>
                  </v-row>
                  <v-divider></v-divider>
                </template>
              </v-virtual-scroll>
            </v-sheet>
          </v-card>
        </div>
      </rs-panes>
    </v-main>

    <v-dialog v-model="comConnectEditShow" width="60%">
      <v-card>
        <v-card-title>
          {{ comConnectEditItem.path }} [{{ comConnectEditItem.name }}]
        </v-card-title>
        <v-card-text>
          <v-combobox v-model="comConnectEditItem.buadrate" :items="buadrateItems" label="波特率" dense spellcheck="false">
          </v-combobox>
          <v-select v-model="comConnectEditItem.databits" :items="databitsItems" label="数据位" dense spellcheck="false">
          </v-select>
          <v-select v-model="comConnectEditItem.stopbits" :items="stopbitsItems" label="停止位" dense spellcheck="false">
          </v-select>
          <v-select v-model="comConnectEditItem.checkBits" :items="checkBitsItems" label="校验" dense spellcheck="false">
          </v-select>
          <v-select v-model="comConnectEditItem.controlBits" :items="controlBitsItems" label="流控" dense
            spellcheck="false">
          </v-select>
          <v-text-field v-model="comConnectEditItem.timeOut" label="读取超时时间(ms)" dense spellcheck="false">
          </v-text-field>
        </v-card-text>
        <v-divider></v-divider>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_com_connect_edit_cancel_clicked">取消</v-btn>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_com_connect_edit_save_clicked">确定</v-btn>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-dialog v-model="netConnectEditShow" width="60%">
      <v-card>
        <v-card-title>
          网络设置
        </v-card-title>
        <v-card-text>
          <v-combobox v-model="netConnectEditItem.type" :items="netTypeItems" label="网络协议" dense spellcheck="false">
          </v-combobox>
          <v-text-field v-model="netConnectEditItem.localPort" label="本地端口" dense spellcheck="false"></v-text-field>
          <v-text-field v-model="netConnectEditItem.remotePort" label="远程端口" dense spellcheck="false"></v-text-field>
          <v-text-field v-model="netConnectEditItem.remoteAddr" label="远程地址" dense spellcheck="false"></v-text-field>
        </v-card-text>
        <v-divider></v-divider>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_net_connect_edit_cancel_clicked">取消</v-btn>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_net_connect_edit_save_clicked">确定</v-btn>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-dialog v-model="quickCmdEditShow" width="60%">
      <v-card>
        <v-card-title>
          快速发送列表设置
        </v-card-title>
        <v-card-text>
          <v-text-field v-model="quickCmdEditItem.name" label="名称" dense spellcheck="false"></v-text-field>
          <v-select v-model="quickCmdEditItem.format" :items="txFormatList" label="格式" dense spellcheck="false">
          </v-select>
          <v-select v-model="quickCmdEditItem.count" :items="txTimesList" label="是否重复" dense spellcheck="false">
          </v-select>
          <v-textarea v-model="quickCmdEditItem.delay" label="重复周期(ms)" dense auto-grow rows="1" spellcheck="false">
          </v-textarea>
          <v-textarea v-model="quickCmdEditItem.message" label="数据" dense auto-grow rows="1" spellcheck="false">
          </v-textarea>
        </v-card-text>
        <v-divider></v-divider>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_quick_cmd_edit_cancel_clicked">取消</v-btn>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_quick_cmd_edit_save_clicked">确定</v-btn>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-dialog v-model="retransmitEditShow" width="60%">
      <v-card>
        <v-card-title>
          转发设置
        </v-card-title>
        <v-card-text>
          <v-text-field v-model="retransmitEditItem.source" label="转发来源" dense spellcheck="false"></v-text-field>
          <v-text-field v-model="retransmitEditItem.destin" label="转发目的" dense spellcheck="false"></v-text-field>
        </v-card-text>
        <v-divider></v-divider>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_retransmit_edit_cancel_clicked">取消</v-btn>
          <v-spacer></v-spacer>
          <v-btn depressed @click="btn_retransmit_edit_save_clicked">确定</v-btn>
          <v-spacer></v-spacer>
          <v-spacer></v-spacer>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-snackbar v-model="snackbar" :timeout="snackbar_time" centered :color="color">
      {{ snackbar_text }}
    </v-snackbar>

  </v-app>
</template>

<script>
import * as monaco from 'monaco-editor'
import * as iconv from 'iconv-lite'
import Plotly from 'plotly.js-basic-dist-min'
import elementResizeDetectorMaker from "element-resize-detector"

export default {
  name: 'App',

  data: () => ({
    chartsStart: false,
    chartsPause: false,

    chartWidth: 0,
    chartHeight: 0,

    chartDatas: [],
    chartDatasCount: 0,
    chartDatasCountMax: 256,

    chartLayout: [],
    chartConfig: [],

    chartPlotTimer: '',

    monacoEditor: {},

    menuShow: true,
    menuPercent: 0,
    menuPercentOld: 50,
    menuIndex: -1,
    menuOldIndex: -1,

    navBarIndex: 0,
    navBarItems: [
      { text: '串口', icon: 'mdi-usb' },
      { text: '网络', icon: 'mdi-server-network' },
      { text: '指令', icon: 'mdi-clipboard-text' },
      { text: '历史', icon: 'mdi-history' },
      { text: '转发', icon: 'mdi-source-pull' },
    ],

    configsShow: false,

    snackbar: false,
    snackbar_time: 2000,
    snackbar_text: '',

    timerUpdateSerials: '',
    timerUpdateConfigs: '',

    txChannelList: ['ALL'],
    txFormatList: ['STR', 'HEX'],
    txAppendList: ['NONE', '\\R', '\\N', '\\R\\N', '\\N\\R'],

    txTimesList: ['ONCE', 'LOOP'],

    txMessage: '',
    txChannel: 'ALL',

    txList: [
      {
        message: '',
        channel: 'ALL',
        format: 'STR',
        append: 'NONE',
      }
    ],

    softwareConfigsList: {
      timestamp: 1,
      dataSource: 1,
      dataFormat: 1,
      rXMain: 1,
      rXSupport: 2,
      tXMain: 1,
      tXSupport: 2,
      textEncode: 1,
      txFormat: 'STR',
      txAppend: 'NONE',
    },

    configsListShow: [
      {}
    ],

    buadrateItems: ['2400', '4800', '9600', '14400', '19200', '38400', '56000', '115200', '128000', '256000'],
    databitsItems: [8, 7, 6, 5],
    stopbitsItems: [1, 2],
    checkBitsItems: ['NONE', 'ODD', 'EVEN', 'MARK', 'SPACE'],
    controlBitsItems: ['NONE', 'HARDWARE', 'SOFTWARE'],
    statusItems: ['OPEN', 'CLOSE'],
    statusItemsColor: ['OPEN', 'CLOSE'],

    comConnectEditShow: false,
    comConnectEditIndex: -1,
    comConnectEditItem: [],
    comConnectList: [],
    comParasList: [],

    netConnectEditShow: false,
    netConnectEditIndex: -1,
    netConnectEditItem: [],

    netTypeItems: ['UDP', 'TCP Server', 'TCP Client'],
    netConnectList: [],
    netParasList: [],

    quickCmdEditShow: false,
    quickCmdEditIndex: -1,
    quickCmdEditItem: [],

    quickCmdList: [
      {
        channel: 'ALL',
        name: 'name',
        format: 'STR',
        append: 'NONE',
        count: 'ONCE',
        delay: 100,
        message: '',
        status: 0
      }
    ],
    quickCmdParasList: [],

    historyList: [],

    retransmitList: [],
    retransmitParasList: [],

    retransmitEditShow: false,
    retransmitEditIndex: -1,
    retransmitEditItem: [],

    allConfigsStored: []
  }),

  computed: {
    color() {
      switch (this.navBarIndex) {
        case 0: return 'blue'
        case 1: return 'teal'
        case 2: return 'brown'
        case 3: return 'indigo'
        case 4: return 'blue'
        case 5: return 'teal'
        case 6: return 'brown'
        default: return 'blue'
      }
    },
    color_light() {
      switch (this.navBarIndex) {
        case 0: return 'blue lighten-5'
        case 1: return 'teal lighten-5'
        case 2: return 'brown lighten-5'
        case 3: return 'indigo lighten-5'
        case 4: return 'blue lighten-5'
        case 5: return 'teal lighten-5'
        case 6: return 'brown lighten-5'
        default: return 'blue lighten-5'
      }
    },
  },

  mounted() {

    // init editor for tx and rx
    monaco.languages.register({ id: "logLang", });
    monaco.languages.setMonarchTokensProvider('logLang', {
      ignoreCase: true,
      tokenizer: {
        root: [
          [/^\[\d{1,3}:\d{2}:\d{2}:\d{1,3}\]/, "m-timestamp"],
          [/\[tx:.*str].*/, { token: "m-tx-str" }],
          [/\[tx:.*hex].*/, { token: "m-tx-hex" }],
          [/\[rx:.*str].*/, { token: "m-rx-str" }],
          [/\[rx:.*hex].*/, { token: "m-rx-hex" }],
        ],
      }
    });
    monaco.editor.defineTheme('logTheme', {
      base: 'vs',
      inherit: true,
      rules: [
        { token: 'm-timestamp', foreground: '#2196F3' },
        { token: 'm-tx-str', foreground: '#00695C' },
        { token: 'm-tx-hex', foreground: '#26A69A' },
        { token: 'm-rx-str', foreground: '#C62828' },
        { token: 'm-rx-hex', foreground: '#E57373' },
      ],
      colors: {
        'editor.background': '#FFFFFF',
        'editor.foreground': '#00695C',
      }
    });
    monaco.editor.setTheme('logTheme');
    this.monacoEditor = monaco.editor.create(document.getElementById('editor'), {
      theme: "logTheme",
      language: 'logLang',
      automaticLayout: true,
      readOnly: false,
      folding: false,
      overviewRulerBorder: false,
      scrollBeyondLastLine: false,
      smoothScrolling: true,
      mouseWheelZoom: true,
      wordWrap: "on",
      wordWrapBreakAfterCharacters: "",
      wordWrapBreakBeforeCharacters: "",
      lineNumbers: false,
      lineNumbersMinChars: 4,
      renderLineHighlight: 'none',
      renderLineHighlightOnlyWhenFocus: true,
      renderIndentGuides: false,
      selectionHighlight: true,
      renderControlCharacters: true,
      fontSize: 11,
      minimap: {
        enabled: false
      },
      scrollbar: {
        vertical: "auto",
        useShadows: false,
        verticalScrollbarSize: 10,
      },
      hideCursorInOverviewRuler: true,
      
      
    });

    // init chart 
    var self = this;
    this.chartDatas = [];
    this.chartLayout = {
      margin: {
        l: 30,
        r: 30,
        t: 30,
        b: 30,
      },
      xaxis: {
        zeroline: false,
        showline: true,
        mirror: 'all',
      },
      yaxis: {
        zeroline: false,
        showline: true,
        mirror: 'all'
      },
      dragmode: "pan",
      showlegend: false,
    };

    this.chartConfig = {
      modeBarButtonsToAdd: [
        'hoverCompare',
        'hoverclosest',
      ],
      modeBarButtonsToRemove: [
        'toImage',
        'select2d',
        'lasso2d'
      ],
      displayModeBar: true,
      responsive: true,
      scrollZoom: true,
      displaylogo: false,
      editSelection: false,
    };
    Plotly.newPlot(document.getElementById("chart"), this.chartDatas, this.chartLayout, this.chartConfig);

    var erd = elementResizeDetectorMaker();
    erd.listenTo(document.getElementById("chart"), function (element) {
      self.$nextTick(function () {
        self.update_chart_graph_size();
      })
    })

    // init ui data of list
    this.init_list_data();

    // get user config
    this.get_user_configs();
    this.timerUpdateConfigs = setInterval(this.update_ui_configs, 5000);

    // check serial period
    this.update_ui_serials();
    this.timerUpdateSerials = setInterval(this.update_ui_serials, 2000);

    // add rx message handle
    window.electronAPI.recvMessages(this.rx_message_deal);
  },
  methods: {
    init_list_data() {
      for (var i = 0; i < 10; i++) {
        var txListItem = {
          message: '',
          channel: 'ALL',
          format: 'STR',
          append: 'NONE'
        };
        this.txList.push(txListItem);
      }

      for (var i = 0; i < 100; i++) {
        var quickCmdListItem = {
          channel: 'ALL',
          name: 'name',
          format: 'STR',
          append: 'NONE',
          count: 'ONCE',
          delay: 100,
          message: '',
          status: 0,
        };
        this.quickCmdList.push(quickCmdListItem);

        var quickCmdParasItem = {
          name: 'name',
          format: 'STR',
          append: 'NONE',
          count: 'ONCE',
          delay: 100,
          message: '',
        };
        this.quickCmdParasList.push(quickCmdParasItem);
      }

      for (var i = 0; i < 9; i++) {
        var netConnectListItem = {
          name: 'NET' + i,
          type: 'UDP',
          localPort: 100 + i,
          remotePort: 100 + i,
          remoteAddr: '127.0.0.1',
          status: 0
        };
        this.netConnectList.push(netConnectListItem);
      }

      for (var i = 0; i < 20; i++) {
        var retransmitListItem = {
          source: "com" + i,
          destin: 'net' + i,
          status: 0
        };
        this.retransmitList.push(retransmitListItem);

        var retransmitParasListItem = {
          source: "com" + i,
          destin: 'net' + i
        };
        this.retransmitParasList.push(retransmitParasListItem);
      }
    },
    btn_chart_start_clicked() {
      this.chartsStart = !this.chartsStart;
      if (this.chartsStart) {
        this.chartPlotTimer = setInterval(this.update_chart_view, 200);
      } else {
        clearInterval(this.chartPlotTimer);
      }
    },
    btn_chart_pause_clicked() {
      this.chartsPause = !this.chartsPause;
    },
    btn_chart_clear_clicked() {
      this.chartDatas = [];
      this.chartDatasCount = 0;
      Plotly.react(document.getElementById("chart"), this.chartDatas, this.chartLayout, this.chartConfig);
    },
    async update_chart_view() {
      if (this.chartsStart == true && this.chartsPause != true) {
        if (this.chartDatasCount > this.chartDatasCountMax) {
          this.chartLayout.xaxis.range = [this.chartDatasCount - this.chartDatasCountMax, this.chartDatasCount];
        }
        Plotly.newPlot(document.getElementById("chart"), this.chartDatas, this.chartLayout, this.chartConfig);
      }
    },
    async update_chart_data(message) {
      if (this.chartsStart == true) {
        //change to str
        var dataString;
        if (this.softwareConfigsList.textEncode == 0) {
          dataString = iconv.decode(message, 'gbk');
        }
        if (this.softwareConfigsList.textEncode == 1) {
          dataString = iconv.decode(message, 'utf-8');
        }
        //split str to data
        var dataStringList = dataString.split('\n');
        for (var i = 0; i < dataStringList.length; i++) {
          if (dataStringList[i].length > 0) {
            var textStringList = dataStringList[i].split(/[,_ ]/);
            if (textStringList.length > 1 && (textStringList[0] == '#' || textStringList[0] == '%')) {
              if (this.chartDatas.length < (textStringList.length - 1)) {
                for (var t = this.chartDatas.length; t < (textStringList.length - 1); t++) {
                  var trace = { type: 'scatter', mode: 'lines', x: [], y: [] };
                  this.chartDatas.push(trace);
                }
              }
              for (var t = 0; t < this.chartDatas.length; t++) {
                this.chartDatas[t].x.push(this.chartDatasCount);
                this.chartDatas[t].y.push(parseFloat(textStringList[t + 1]));
              }
              this.chartDatasCount++;
            }
          }
        }
      }
    },
    async update_chart_graph_size() {
      console.log("update_chart_graph_size");
      var update = {
        'width': document.getElementById("chart").offsetWidth,
        'height': document.getElementById("chart").offsetHeight,
        'margin': this.chartLayout.margin,
      }
      Plotly.relayout(document.getElementById("chart"), update);
    },
    async retransmit_data(src, data) {
      for (var i = 0; i < this.retransmitList.length; i++) {
        if (this.retransmitList[i].status
          && src == this.retransmitList[i].source.toUpperCase()
          && src != this.retransmitList[i].destin.toUpperCase()) {
          var message = {
            path: this.retransmitList[i].destin.toUpperCase(),
            data: data
          }
          window.electronAPI.sendMessages(message);
        }
      }
    },
    //UI functions============================================================================================
    btn_com_connect_state_clicked(item) {
      this.change_serial_status(item);
    },
    btn_com_connect_edit_clicked(item) {
      this.comConnectEditIndex = this.comConnectList.indexOf(item);
      this.comConnectEditItem = Object.assign({}, item);
      this.comConnectEditShow = true;
    },
    btn_com_connect_edit_save_clicked() {
      this.comConnectEditShow = false;
      /* When the user change the baudrate to custom value and submits it directly
         the value of Vue bidirectional binding takes time to take effect
         so do a little delay here */
      setTimeout(() => {
        Object.assign(this.comConnectList[this.comConnectEditIndex], this.comConnectEditItem);

        var incomParasList = 0;
        for (var i = 0; i < this.comParasList.length; i++) {
          if (this.comParasList[i].path == this.comConnectEditItem.path &&
            this.comParasList[i].name == this.comConnectEditItem.name
          ) {
            this.comParasList[i].buadrate = this.comConnectEditItem.buadrate;
            this.comParasList[i].databits = this.comConnectEditItem.databits;
            this.comParasList[i].stopbits = this.comConnectEditItem.stopbits;
            this.comParasList[i].checkBits = this.comConnectEditItem.checkBits;
            this.comParasList[i].controlBits = this.comConnectEditItem.controlBits;
            this.comParasList[i].timeOut = this.comConnectEditItem.timeOut;
            incomParasList = 1;
            break;
          }
        }
        if (incomParasList == 0) {
          var comParasItem = {
            path: this.comConnectEditItem.path,
            name: this.comConnectEditItem.name,
            buadrate: this.comConnectEditItem.buadrate,
            databits: this.comConnectEditItem.databits,
            stopbits: this.comConnectEditItem.stopbits,
            checkBits: this.comConnectEditItem.checkBits,
            controlBits: this.comConnectEditItem.controlBits,
            timeOut: this.comConnectEditItem.timeOut,
          };
          this.comParasList.push(comParasItem);
        }
      }, 100);
    },
    btn_com_connect_edit_cancel_clicked() {
      this.comConnectEditShow = false;
    },

    btn_net_connect_state_clicked(item) {
      this.change_net_status(item);
    },
    btn_net_connect_edit_clicked(item) {
      this.netConnectEditIndex = this.netConnectList.indexOf(item);
      this.netConnectEditItem = Object.assign({}, item);
      this.netConnectEditShow = true;
    },
    btn_net_connect_edit_save_clicked() {
      this.netConnectEditShow = false;
      setTimeout(() => {
        Object.assign(this.netConnectList[this.netConnectEditIndex], this.netConnectEditItem);

        var innetParasList = 0;
        for (var i = 0; i < this.netParasList.length; i++) {
          if (this.netParasList[i].name == this.netConnectEditItem.name) {
            this.netParasList[i].type = this.netConnectEditItem.type;
            this.netParasList[i].localPort = this.netConnectEditItem.localPort;
            this.netParasList[i].remotePort = this.netConnectEditItem.remotePort;
            this.netParasList[i].remoteAddr = this.netConnectEditItem.remoteAddr;
            innetParasList = 1;
            break;
          }
        }
        if (innetParasList == 0) {
          var netParasItem = {
            name: this.netConnectEditItem.name,
            type: this.netConnectEditItem.type,
            localPort: this.netConnectEditItem.localPort,
            remotePort: this.netConnectEditItem.remotePort,
            remoteAddr: this.netConnectEditItem.remoteAddr,
          };
          this.netParasList.push(netParasItem);
        }
      }, 100);
    },
    btn_net_connect_edit_cancel_clicked() {
      this.netConnectEditShow = false;
    },

    btn_quick_cmd_format_clicked(item) {
      if (item.format == 'STR') {
        item.format = 'HEX';
      } else {
        item.format = 'STR';
      }
      this.quickCmdParasList[this.quickCmdList.indexOf(item)].format = item.format;
    },
    btn_quick_cmd_channel_clicked(item) {
      /* check the next channel  is valid ?*/
      var index = this.txChannelList.indexOf(item.channel) + 1;
      if (index < this.txChannelList.length) {
        item.channel = this.txChannelList[index];
      } else {
        item.channel = this.txChannelList[0];
      }
    },
    btn_quick_cmd_times_clicked(item) {
      if (item.count == 'ONCE') {
        item.count = 'LOOP';
      } else {
        item.count = 'ONCE';
      }
      this.quickCmdParasList[this.quickCmdList.indexOf(item)].count = item.count;
    },
    btn_quick_cmd_send_clicked(item) {
      item.status = 1;
      /* hex not append and str use global append */
      if (item.format == 'STR') {
        item.append = this.softwareConfigsList.txAppend;
      } else {
        item.append = 'NONE';
      }
      if (item.timer != undefined) {
        clearInterval(item.timer);
        item.timer = undefined;
        item.status = 0;
        return;
      }
      this.send_item_message(item);
      if (item.count == 'ONCE') {
        setTimeout(() => {
          item.status = 0;
        }, 200);
      }
      if (item.count == 'LOOP') {
        item.timer = setInterval(() => {
          this.send_item_message(item);
        }, item.delay);
      }
    },
    btn_quick_cmd_edit_clicked(item) {
      this.quickCmdEditIndex = this.quickCmdList.indexOf(item);
      this.quickCmdEditItem = Object.assign({}, item);
      this.quickCmdEditShow = true;
    },
    btn_quick_cmd_edit_save_clicked() {
      this.quickCmdEditShow = false;
      setTimeout(() => {
        Object.assign(this.quickCmdList[this.quickCmdEditIndex], this.quickCmdEditItem);

        this.quickCmdParasList[this.quickCmdEditIndex].name = this.quickCmdEditItem.name;
        this.quickCmdParasList[this.quickCmdEditIndex].format = this.quickCmdEditItem.format;
        this.quickCmdParasList[this.quickCmdEditIndex].append = this.quickCmdEditItem.append;
        this.quickCmdParasList[this.quickCmdEditIndex].count = this.quickCmdEditItem.count;
        this.quickCmdParasList[this.quickCmdEditIndex].delay = this.quickCmdEditItem.delay;
        this.quickCmdParasList[this.quickCmdEditIndex].message = this.quickCmdEditItem.message;
      }, 100);
    },
    btn_quick_cmd_edit_cancel_clicked() {
      this.quickCmdEditShow = false;
    },

    btn_retransmit_edit_clicked(item) {
      this.retransmitEditIndex = this.retransmitList.indexOf(item);
      this.retransmitEditItem = Object.assign({}, item);
      this.retransmitEditShow = true;
    },
    btn_retransmit_edit_save_clicked() {
      this.retransmitEditShow = false;
      setTimeout(() => {
        Object.assign(this.retransmitList[this.retransmitEditIndex], this.retransmitEditItem);

        this.retransmitParasList[this.retransmitEditIndex].source = this.retransmitEditItem.source;
        this.retransmitParasList[this.retransmitEditIndex].destin = this.retransmitEditItem.destin;
      }, 100);
    },
    btn_retransmit_edit_cancel_clicked() {
      this.retransmitEditShow = false;
    },

    btn_history_format_clicked(item) {
      if (item.format == 'STR') {
        item.format = 'HEX';
      } else {
        item.format = 'STR';
      }
    },
    btn_history_channel_clicked(item) {
      /* check the next channel  is valid ?*/
      var index = this.txChannelList.indexOf(item.channel) + 1;
      if (index < this.txChannelList.length) {
        item.channel = this.txChannelList[index];
      } else {
        item.channel = this.txChannelList[0];
      }
    },
    btn_history_delete_clicked(item) {
      this.historyList.splice(this.historyList.indexOf(item), 1);
    },
    btn_history_send_clicked(item) {
      this.send_item_message(item);
    },

    btn_tx_format_clicked() {
      if (this.softwareConfigsList.txFormat == 'STR') {
        this.softwareConfigsList.txFormat = 'HEX';
      } else {
        this.softwareConfigsList.txFormat = 'STR';
      }
    },
    btn_tx_channel_clicked() {
      /* check the next channel  is valid ?*/
      var index = this.txChannelList.indexOf(this.txChannel) + 1;
      if (index < this.txChannelList.length) {
        this.txChannel = this.txChannelList[index];
      } else {
        this.txChannel = this.txChannelList[0];
      }
    },
    btn_tx_append_clicked() {
      /* check the next append  is valid ?*/
      var index = this.txAppendList.indexOf(this.softwareConfigsList.txAppend) + 1;
      if (index < this.txAppendList.length) {
        this.softwareConfigsList.txAppend = this.txAppendList[index];
      } else {
        this.softwareConfigsList.txAppend = this.txAppendList[0];
      }
    },
    btn_tx_send_clicked() {
      let data;
      if (this.softwareConfigsList.txFormat == 'STR') {
        if (this.softwareConfigsList.textEncode == 0) {
          data = iconv.encode(this.txMessage, 'gbk');
          console.log(data)
        }
        if (this.softwareConfigsList.textEncode == 1) {
          data = iconv.encode(this.txMessage, 'utf-8');
          console.log(data)
        }
      }
      if (this.softwareConfigsList.txFormat == 'HEX') {
        data = this.utils_hex_to_uint8array(this.txMessage);
      }
      if (this.softwareConfigsList.txAppend == '\\R') {
        var new_data = new Uint8Array(data.length + 1);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0D;
        data = new_data;
      }
      if (this.softwareConfigsList.txAppend == '\\N') {
        var new_data = new Uint8Array(data.length + 1);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0A;
        data = new_data;
      }
      if (this.softwareConfigsList.txAppend == '\\R\\N') {
        var new_data = new Uint8Array(data.length + 2);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0D;
        new_data[data.length + 1] = 0x0A;
        data = new_data;
      }
      if (this.softwareConfigsList.txAppend == '\\N\\R') {
        var new_data = new Uint8Array(data.length + 2);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0A;
        new_data[data.length + 1] = 0x0D;
        data = new_data;
      }

      if (data == null) {
        return;
      }

      var message = {
        path: this.txChannel,
        data: data
      }
      window.electronAPI.sendMessages(message);

      // Show to UI
      let textPrev = [];
      let textString = [];
      if (this.softwareConfigsList.timestamp > 0) {
        textPrev += "[" + this.utils_get_timestamp() + "]";
      }
      if (this.softwareConfigsList.dataSource > 0) {
        textPrev += "[TX:" + this.txChannel + "]";
      }

      if (this.softwareConfigsList.tXMain == 1) {
        if (this.softwareConfigsList.textEncode == 0) {
          var dataStringList = iconv.decode(message.data, 'gbk').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
        if (this.softwareConfigsList.textEncode == 1) {
          var dataStringList = iconv.decode(message.data, 'utf-8').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
      }
      if (this.softwareConfigsList.tXMain == 2) {
        textString += textPrev;
        if (this.softwareConfigsList.dataFormat > 0) {
          textString += '[HEX]';
        }
        textString += this.utils_uint8array_to_hex(message.data) + "\n";
      }

      if (this.softwareConfigsList.tXSupport == 1) {
        if (this.softwareConfigsList.textEncode == 0) {
          var dataStringList = iconv.decode(message.data, 'gbk').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
        if (this.softwareConfigsList.textEncode == 1) {
          var dataStringList = iconv.decode(message.data, 'utf-8').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
      }
      if (this.softwareConfigsList.tXSupport == 2) {
        textString += textPrev;
        if (this.softwareConfigsList.dataFormat > 0) {
          textString += '[HEX]';
        }
        textString += this.utils_uint8array_to_hex(message.data) + "\n";
      }

      const model = this.monacoEditor.getModel();
      const lineCount = model.getLineCount();
      const lastLineLength = model.getLineMaxColumn(lineCount);
      const range = new monaco.Range(lineCount, lastLineLength, lineCount, lastLineLength);

      this.monacoEditor.getModel().applyEdits([{ forceMoveMarkers: true, range: range, text: textString },]);
      this.monacoEditor.revealLine(model.getLineCount());

      //add to history list
      if (this.txMessage.length > 0) {
        var historyListItem = {
          channel: this.txChannel,
          format: this.softwareConfigsList.txFormat,
          message: this.txMessage
        };
        if (this.historyList.length == 0) {
          this.historyList.unshift(historyListItem);
        } else if (historyListItem.message != this.historyList[0].message) {
          this.historyList.unshift(historyListItem);
        }
        if (this.historyList.length > 100) {
          this.historyList.pop();
        }
      }
    },

    btn_tx_list_format_clicked(item) {
      if (item.format == 'STR') {
        item.format = 'HEX';
      } else {
        item.format = 'STR';
      }
    },
    btn_tx_list_channel_clicked(item) {
      /* check the next channel  is valid ?*/
      var index = this.txChannelList.indexOf(item.channel) + 1;
      if (index < this.txChannelList.length) {
        item.channel = this.txChannelList[index];
      } else {
        item.channel = this.txChannelList[0];
      }
    },
    btn_tx_list_append_clicked(item) {
      /* check the next append  is valid ?*/
      var index = this.txAppendList.indexOf(item.append) + 1;
      if (index < this.txAppendList.length) {
        item.append = this.txAppendList[index];
      } else {
        item.append = this.txAppendList[0];
      }
    },
    btn_tx_list_send_clicked(item) {
      this.send_item_message(item);
    },

    btn_menu_set_clicked(index) {
      /* record menu index */
      this.menuIndex = index;

      /* if click the differ menu we show it and changed */
      if (this.menuOldIndex != index) {
        this.menuOldIndex = index;
        this.menuPercent = this.menuPercentOld;
        this.menuShow = true;
        return;
      }

      /* if click the same menu we close it */
      this.menuShow = !this.menuShow;
      if (this.menuShow) {
        this.menuPercent = this.menuPercentOld;
      } else {
        this.menuIndex = -1;
        this.menuOldIndex = -1;
        this.menuPercentOld = this.menuPercent;
        this.menuPercent = 0;
      }
    },

    btn_win_min_clicked() {
      console.log("btn_win_min_clicked");
      window.electronAPI.setWindowMin();
    },
    btn_win_max_clicked() {
      console.log("btn_win_max_clicked");
      window.electronAPI.setWindowMax();
    },
    btn_win_exit_clicked() {
      console.log("btn_win_exit_clicked");
      window.electronAPI.setWindowExit();
    },

    btn_editor_clear_clicked() {
      console.log("btn_editor_clear_clicked");
      this.monacoEditor.setValue("");
    },
    btn_editor_saved_clicked() {
      console.log("btn_editor_saved_clicked");
      let data = this.monacoEditor.getValue();
      console.log(data);
      this.get_user_serials();
    },
    send_item_message(item) {
      let data;
      if (item.format == 'STR') {
        if (this.softwareConfigsList.textEncode == 0) {
          data = iconv.encode(item.message, 'gbk');
          console.log(data)
        }
        if (this.softwareConfigsList.textEncode == 1) {
          data = iconv.encode(item.message, 'utf-8');
          console.log(data)
        }
      }
      if (item.format == 'HEX') {
        data = this.utils_hex_to_uint8array(item.message);
      }
      if (item.append == '\\R') {
        var new_data = new Uint8Array(data.length + 1);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0D;
        data = new_data;
      }
      if (item.append == '\\N') {
        var new_data = new Uint8Array(data.length + 1);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0A;
        data = new_data;
      }
      if (item.append == '\\R\\N') {
        var new_data = new Uint8Array(data.length + 2);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0D;
        new_data[data.length + 1] = 0x0A;
        data = new_data;
      }
      if (item.append == '\\N\\R') {
        var new_data = new Uint8Array(data.length + 2);
        for (var i = 0; i < data.length; i++) {
          new_data[i] = data[i];
        }
        new_data[data.length] = 0x0A;
        new_data[data.length + 1] = 0x0D;
        data = new_data;
      }

      if (data == null) {
        return;
      }

      var message = {
        path: item.channel,
        data: data
      }
      window.electronAPI.sendMessages(message);

      // Show to UI
      let textPrev = [];
      let textString = [];
      if (this.softwareConfigsList.timestamp > 0) {
        textPrev += "[" + this.utils_get_timestamp() + "]";
      }
      if (this.softwareConfigsList.dataSource > 0) {
        textPrev += "[TX:" + item.channel + "]";
      }

      if (this.softwareConfigsList.tXMain == 1) {
        if (this.softwareConfigsList.textEncode == 0) {
          var dataStringList = iconv.decode(message.data, 'gbk').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
        if (this.softwareConfigsList.textEncode == 1) {
          var dataStringList = iconv.decode(message.data, 'utf-8').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
      }
      if (this.softwareConfigsList.tXMain == 2) {
        textString += textPrev;
        if (this.softwareConfigsList.dataFormat > 0) {
          textString += '[HEX]';
        }
        textString += this.utils_uint8array_to_hex(message.data) + "\n";
      }

      if (this.softwareConfigsList.tXSupport == 1) {
        if (this.softwareConfigsList.textEncode == 0) {
          var dataStringList = iconv.decode(message.data, 'gbk').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
        if (this.softwareConfigsList.textEncode == 1) {
          var dataStringList = iconv.decode(message.data, 'utf-8').split('\n');
          for (var i = 0; i < dataStringList.length; i++) {
            if (dataStringList[i].length > 0) {
              textString += textPrev;
              if (this.softwareConfigsList.dataFormat > 0) {
                textString += '[STR]';
              }
              textString += dataStringList[i];
              textString += '\n';
            }
          }
        }
      }
      if (this.softwareConfigsList.tXSupport == 2) {
        textString += textPrev;
        if (this.softwareConfigsList.dataFormat > 0) {
          textString += '[HEX]';
        }
        textString += this.utils_uint8array_to_hex(message.data) + "\n";
      }

      const model = this.monacoEditor.getModel();
      const lineCount = model.getLineCount();
      const lastLineLength = model.getLineMaxColumn(lineCount);
      const range = new monaco.Range(lineCount, lastLineLength, lineCount, lastLineLength);

      this.monacoEditor.getModel().applyEdits([{ forceMoveMarkers: true, range: range, text: textString },]);
      this.monacoEditor.revealLine(model.getLineCount());

      //add to history list
      if (item.message.length > 0) {
        var historyListItem = {
          channel: item.channel,
          format: item.format,
          message: item.message
        };
        if (this.historyList.length == 0) {
          this.historyList.unshift(historyListItem);
        } else if (historyListItem.message != this.historyList[0].message) {
          this.historyList.unshift(historyListItem);
        }
        if (this.historyList.length > 100) {
          this.historyList.pop();
        }
      }
    },
    rx_message_deal(event, message) {
      if (message.type == 'com_status') {
        if (parseInt(message.data) == 1) {
          this.txChannelList.push(message.path);
        } else {
          for (var i = 0; i < this.txChannelList.length; i++) {
            if (message.path == this.txChannelList[i]) {
              this.txChannelList.splice(i, 1);
              break;
            }
          }
        }
        for (var i = 0; i < this.comConnectList.length; i++) {
          if (message.path == this.comConnectList[i].path) {
            this.comConnectList[i].status = parseInt(message.data);
            if (message.info) {
              this.snackbar = true;
              this.snackbar_time = 3000;
              this.snackbar_text = message.path + ':' + message.info;
            }
            break;
          }
        }
      }
      if (message.type == 'com_message') {
        let textPrev = [];
        let textString = [];
        if (this.softwareConfigsList.timestamp > 0) {
          textPrev += "[" + this.utils_get_timestamp() + "]";
        }
        if (this.softwareConfigsList.dataSource > 0) {
          textPrev += "[RX:" + message.path + "]";
        }

        if (this.softwareConfigsList.rXMain == 1) {
          if (this.softwareConfigsList.textEncode == 0) {
            var dataStringList = iconv.decode(message.data, 'gbk').split('\n');
            for (var i = 0; i < dataStringList.length; i++) {
              if (dataStringList[i].length > 0) {
                textString += textPrev;
                if (this.softwareConfigsList.dataFormat > 0) {
                  textString += '[STR]';
                }
                textString += dataStringList[i];
                textString += '\n';
              }
            }
          }
          if (this.softwareConfigsList.textEncode == 1) {
            var dataStringList = iconv.decode(message.data, 'utf-8').split('\n');
            for (var i = 0; i < dataStringList.length; i++) {
              if (dataStringList[i].length > 0) {
                textString += textPrev;
                if (this.softwareConfigsList.dataFormat > 0) {
                  textString += '[STR]';
                }
                textString += dataStringList[i];
                textString += '\n';
              }
            }
          }
        }
        if (this.softwareConfigsList.rXMain == 2) {
          textString += textPrev;
          if (this.softwareConfigsList.dataFormat > 0) {
            textString += '[HEX]';
          }
          textString += this.utils_uint8array_to_hex(message.data) + "\n";
        }

        if (this.softwareConfigsList.rXSupport == 1) {
          if (this.softwareConfigsList.textEncode == 0) {
            var dataStringList = iconv.decode(message.data, 'gbk').split('\n');
            for (var i = 0; i < dataStringList.length; i++) {
              if (dataStringList[i].length > 0) {
                textString += textPrev;
                if (this.softwareConfigsList.dataFormat > 0) {
                  textString += '[STR]';
                }
                textString += dataStringList[i];
                textString += '\n';
              }
            }
          }
          if (this.softwareConfigsList.textEncode == 1) {
            var dataStringList = iconv.decode(message.data, 'utf-8').split('\n');
            for (var i = 0; i < dataStringList.length; i++) {
              if (dataStringList[i].length > 0) {
                textString += textPrev;
                if (this.softwareConfigsList.dataFormat > 0) {
                  textString += '[STR]';
                }
                textString += dataStringList[i];
                textString += '\n';
              }
            }
          }
        }
        if (this.softwareConfigsList.rXSupport == 2) {
          textString += textPrev;
          if (this.softwareConfigsList.dataFormat > 0) {
            textString += '[HEX]';
          }
          textString += this.utils_uint8array_to_hex(message.data) + "\n";
        }

        const model = this.monacoEditor.getModel();
        const lineCount = model.getLineCount();
        const lastLineLength = model.getLineMaxColumn(lineCount);
        const range = new monaco.Range(lineCount, lastLineLength, lineCount, lastLineLength);

        this.monacoEditor.getModel().applyEdits([{ forceMoveMarkers: true, range: range, text: textString },]);
        this.monacoEditor.revealLine(model.getLineCount());

        this.update_chart_data(message.data);

        this.retransmit_data(message.path, message.data);
      }
      if (message.type == 'net_status') {
        console.log(message)
        if (parseInt(message.data) == 1) {
          this.txChannelList.push(message.path);
        } else {
          for (var i = 0; i < this.txChannelList.length; i++) {
            if (message.path == this.txChannelList[i]) {
              this.txChannelList.splice(i, 1);
              break;
            }
          }
        }
        for (var i = 0; i < this.netConnectList.length; i++) {
          if (message.path == this.netConnectList[i].name) {
            this.netConnectList[i].status = parseInt(message.data);
            if (message.info) {
              this.snackbar = true;
              this.snackbar_time = 3000;
              this.snackbar_text = message.path + ':' + message.info;
            }
            break;
          }
        }
      }
      if (message.type == 'net_message') {
        console.log(message)
        let textPrev = [];
        let textString = [];
        if (this.softwareConfigsList.timestamp > 0) {
          textPrev += "[" + this.utils_get_timestamp() + "]";
        }
        if (this.softwareConfigsList.dataSource > 0) {
          textPrev += "[RX:" + message.path + "|" + message.addr + ":" + message.port + "]";
        }

        if (this.softwareConfigsList.rXMain == 1) {
          textString += textPrev;
          if (this.softwareConfigsList.dataFormat > 0) {
            textString += '[STR]';
          }
          if (this.softwareConfigsList.textEncode == 0) {
            textString += iconv.decode(message.data, 'gbk');
            if (textString.at(textString.length - 1) != '\n') {
              textString += '\n';
            }
          }
          if (this.softwareConfigsList.textEncode == 1) {
            textString += iconv.decode(message.data, 'utf-8');
            if (textString.at(textString.length - 1) != '\n') {
              textString += '\n';
            }
          }
        }
        if (this.softwareConfigsList.rXMain == 2) {
          textString += textPrev;
          if (this.softwareConfigsList.dataFormat > 0) {
            textString += '[HEX]';
          }
          textString += this.utils_uint8array_to_hex(message.data) + "\n";
        }

        if (this.softwareConfigsList.rXSupport == 1) {
          textString += textPrev;
          if (this.softwareConfigsList.dataFormat > 0) {
            textString += '[STR]';
          }
          if (this.softwareConfigsList.textEncode == 0) {
            textString += iconv.decode(message.data, 'gbk');
            if (textString.at(textString.length - 1) != '\n') {
              textString += '\n';
            }
          }
          if (this.softwareConfigsList.textEncode == 1) {
            textString += iconv.decode(message.data, 'utf-8');
            if (textString.at(textString.length - 1) != '\n') {
              textString += '\n';
            }
          }
        }
        if (this.softwareConfigsList.rXSupport == 2) {
          textString += textPrev;
          if (this.softwareConfigsList.dataFormat > 0) {
            textString += '[HEX]';
          }
          textString += this.utils_uint8array_to_hex(message.data) + "\n";
        }

        console.log(textString);
        const model = this.monacoEditor.getModel();
        const lineCount = model.getLineCount();
        const lastLineLength = model.getLineMaxColumn(lineCount);
        const range = new monaco.Range(lineCount, lastLineLength, lineCount, lastLineLength);

        this.monacoEditor.getModel().applyEdits([{ forceMoveMarkers: true, range: range, text: textString },]);
        this.monacoEditor.revealLine(model.getLineCount());

        this.update_chart_data(message.data);

        this.retransmit_data(message.path, message.data);
      }
    },
    btn_tx_channel_close_clicked(item) {
      console.log(item);
      for (var i = 0; i < this.comConnectList.length; i++) {
        if (item == this.comConnectList[i].path) {
          this.change_serial_status(this.comConnectList[i]);
          break;
        }
      }
      for (var i = 0; i < this.netConnectList.length; i++) {
        if (item == this.netConnectList[i].name) {
          this.change_net_status(this.netConnectList[i]);
          break;
        }
      }
    },
    //UI functions end=========================================================================================

    //Support functions========================================================================================
    utils_get_timestamp() {
      const t = new Date();
      return (t.toLocaleTimeString().split(" ")[0] + ":" + t.getMilliseconds().toString().padStart(3, 0));
    },
    utils_uint8array_to_hex(buf) {
      return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(' ').toUpperCase();
    },
    utils_uint8array_to_str(buf) {
      return String.fromCharCode.apply(null, buf);
    },
    utils_hex_to_uint8array(hex) {
      hex = hex.replace(/\s*/g, "");//remove space
      var uint8 = [];
      for (let i = 0, j = 0; i < hex.length; i += 2) {
        uint8[j++] = parseInt(hex.substring(i, i + 2), 16);
      }
      var arrayBuffer_uint8 = new Uint8Array(uint8.length)
      for (let i = 0; i < uint8.length; i++) {
        arrayBuffer_uint8[i] = uint8[i];
      }
      return arrayBuffer_uint8;
    },
    utils_str_to_uint8array(str) {
      var arrayBuffer_uint8 = new Uint8Array(str.length)
      for (let i = 0; i < str.length; i++) {
        arrayBuffer_uint8[i] = str.charCodeAt(i);
      }
      return arrayBuffer_uint8;
    },
    //Others functions=========================================================================================
    async get_user_configs() {
      var configs = await window.electronAPI.getConfigs();
      console.log(configs);

      if (configs.hasOwnProperty("softwareConfigsList") == true) {
        if (configs.softwareConfigsList.timestamp == 0 || configs.softwareConfigsList.timestamp == 1) {
          this.softwareConfigsList.timestamp = configs.softwareConfigsList.timestamp;
        }
        if (configs.softwareConfigsList.dataSource == 0 || configs.softwareConfigsList.dataSource == 1) {
          this.softwareConfigsList.dataSource = configs.softwareConfigsList.dataSource;
        }
        if (configs.softwareConfigsList.dataFormat == 0 || configs.softwareConfigsList.dataFormat == 1) {
          this.softwareConfigsList.dataFormat = configs.softwareConfigsList.dataFormat;
        }
        if (configs.softwareConfigsList.rXMain == 0 || configs.softwareConfigsList.rXMain == 1 || configs.softwareConfigsList.rXMain == 2) {
          this.softwareConfigsList.rXMain = configs.softwareConfigsList.rXMain;
        }
        if (configs.softwareConfigsList.rXSupport == 0 || configs.softwareConfigsList.rXSupport == 1 || configs.softwareConfigsList.rXSupport == 2) {
          this.softwareConfigsList.rXSupport = configs.softwareConfigsList.rXSupport;
        }
        if (configs.softwareConfigsList.tXMain == 0 || configs.softwareConfigsList.tXMain == 1 || configs.softwareConfigsList.tXMain == 2) {
          this.softwareConfigsList.tXMain = configs.softwareConfigsList.tXMain;
        }
        if (configs.softwareConfigsList.tXSupport == 0 || configs.softwareConfigsList.tXSupport == 1 || configs.softwareConfigsList.tXSupport == 2) {
          this.softwareConfigsList.tXSupport = configs.softwareConfigsList.tXSupport;
        }
        if (configs.softwareConfigsList.textEncode == 0 || configs.softwareConfigsList.textEncode == 1) {
          this.softwareConfigsList.textEncode = configs.softwareConfigsList.textEncode;
        }
        if (configs.softwareConfigsList.txFormat == 'STR' || configs.softwareConfigsList.txFormat == 'HEX') {
          this.softwareConfigsList.txFormat = configs.softwareConfigsList.txFormat;
        }
        if (configs.softwareConfigsList.txAppend == 'NONE' || configs.softwareConfigsList.txAppend == '\\R'
          || configs.softwareConfigsList.txAppend == '\\N' || configs.softwareConfigsList.txAppend == '\\R\\N'
          || configs.softwareConfigsList.txAppend == '\\N\\R') {
          this.softwareConfigsList.txAppend = configs.softwareConfigsList.txAppend;
        }
      }
      if (configs.hasOwnProperty("quickCmdParasList") == true) {
        for (var i = 0; i < configs.quickCmdParasList.length; i++) {
          this.quickCmdParasList[i].name = configs.quickCmdParasList[i].name;
          this.quickCmdParasList[i].format = configs.quickCmdParasList[i].format;
          this.quickCmdParasList[i].append = configs.quickCmdParasList[i].append;
          this.quickCmdParasList[i].count = configs.quickCmdParasList[i].count;
          this.quickCmdParasList[i].delay = configs.quickCmdParasList[i].delay;
          this.quickCmdParasList[i].message = configs.quickCmdParasList[i].message;

          this.quickCmdList[i].name = configs.quickCmdParasList[i].name;
          this.quickCmdList[i].format = configs.quickCmdParasList[i].format;
          this.quickCmdList[i].append = configs.quickCmdParasList[i].append;
          this.quickCmdList[i].count = configs.quickCmdParasList[i].count;
          this.quickCmdList[i].delay = configs.quickCmdParasList[i].delay;
          this.quickCmdList[i].message = configs.quickCmdParasList[i].message;
        }
      }
      if (configs.hasOwnProperty("retransmitParasList") == true) {
        for (var i = 0; i < configs.retransmitParasList.length; i++) {
          this.retransmitParasList[i].source = configs.retransmitParasList[i].source;
          this.retransmitParasList[i].destin = configs.retransmitParasList[i].destin;

          this.retransmitList[i].source = configs.retransmitParasList[i].source;
          this.retransmitList[i].destin = configs.retransmitParasList[i].destin;
        }
      }
      if (configs.hasOwnProperty("historyList") == true) {
        for (var i = 0; i < configs.historyList.length; i++) {
          var historyListItem = {
            channel: configs.historyList[i].channel,
            format: configs.historyList[i].format,
            message: configs.historyList[i].message
          };
          this.historyList.push(historyListItem);
        }
      }
      if (configs.hasOwnProperty("comParasList") == true) {
        for (var i = 0; i < configs.comParasList.length; i++) {
          var comParasItem = {
            path: configs.comParasList[i].path,
            name: configs.comParasList[i].name,
            buadrate: configs.comParasList[i].buadrate,
            databits: configs.comParasList[i].databits,
            stopbits: configs.comParasList[i].stopbits,
            checkBits: configs.comParasList[i].checkBits,
            controlBits: configs.comParasList[i].controlBits,
            timeOut: configs.comParasList[i].timeOut,
          };
          this.comParasList.push(comParasItem);
        }
      }
      if (configs.hasOwnProperty("netParasList") == true) {
        for (var i = 0; i < configs.netParasList.length; i++) {
          var netParasItem = {
            name: configs.netParasList[i].name,
            type: configs.netParasList[i].type,
            localPort: configs.netParasList[i].localPort,
            remotePort: configs.netParasList[i].remotePort,
            remoteAddr: configs.netParasList[i].remoteAddr
          };
          this.netParasList.push(netParasItem);

          for (var j = 0; i < this.netConnectList.length; j++) {
            if (this.netConnectList[j].name == configs.netParasList[i].name) {
              this.netConnectList[j].type = configs.netParasList[i].type;
              this.netConnectList[j].localPort = configs.netParasList[i].localPort;
              this.netConnectList[j].remotePort = configs.netParasList[i].remotePort;
              this.netConnectList[j].remoteAddr = configs.netParasList[i].remoteAddr;
              break;
            }
          }
        }
      }

      this.allConfigsStored.softwareConfigsListJson = JSON.stringify(this.softwareConfigsList);
      this.allConfigsStored.quickCmdParasListJson = JSON.stringify(this.quickCmdParasList);
      this.allConfigsStored.historyListJson = JSON.stringify(this.historyList);
      this.allConfigsStored.retransmitParasListJson = JSON.stringify(this.retransmitParasList);
      this.allConfigsStored.comParasListJson = JSON.stringify(this.comParasList);
      this.allConfigsStored.netParasListJson = JSON.stringify(this.netParasList);
    },
    async set_user_configs(config) {
      await window.electronAPI.setConfigs(config);
    },
    async update_ui_configs() {
      var softwareConfigsListJsonTmp = JSON.stringify(this.softwareConfigsList);
      if (this.allConfigsStored.softwareConfigsListJson != softwareConfigsListJsonTmp) {
        console.log("update softwareConfigsListJson")
        this.allConfigsStored.softwareConfigsListJson = softwareConfigsListJsonTmp;
        window.electronAPI.setConfigs('softwareConfigsList', this.softwareConfigsList);
      }

      var quickCmdParasListJsonTmp = JSON.stringify(this.quickCmdParasList);
      if (this.allConfigsStored.quickCmdParasListJson != quickCmdParasListJsonTmp) {
        console.log("update quickCmdParasListJson")
        this.allConfigsStored.quickCmdParasListJson = quickCmdParasListJsonTmp;
        window.electronAPI.setConfigs('quickCmdParasList', this.quickCmdParasList);
      }

      var historyListJsonTmp = JSON.stringify(this.historyList);
      if (this.allConfigsStored.historyListJson != historyListJsonTmp) {
        console.log("update historyListJson")
        this.allConfigsStored.historyListJson = historyListJsonTmp;
        window.electronAPI.setConfigs('historyList', this.historyList);
      }

      var retransmitParasListJsonTmp = JSON.stringify(this.retransmitParasList);
      if (this.allConfigsStored.retransmitParasListJson != retransmitParasListJsonTmp) {
        console.log("update retransmitParasListJson")
        this.allConfigsStored.retransmitParasListJson = retransmitParasListJsonTmp;
        window.electronAPI.setConfigs('retransmitParasList', this.retransmitParasList);
      }

      var comParasListJsonTmp = JSON.stringify(this.comParasList);
      if (this.allConfigsStored.comParasListJson != comParasListJsonTmp) {
        console.log("update comParasList")
        this.allConfigsStored.comParasListJson = comParasListJsonTmp;
        window.electronAPI.setConfigs('comParasList', this.comParasList);
      }

      var netParasListJsonTmp = JSON.stringify(this.netParasList);
      if (this.allConfigsStored.netParasListJson != netParasListJsonTmp) {
        console.log("update netParasList")
        this.allConfigsStored.netParasListJson = netParasListJsonTmp;
        window.electronAPI.setConfigs('netParasList', this.netParasList);
      }
    },
    async get_user_serials() {
      console.log("get_user_serials");
      var serials = await window.electronAPI.getSerials();
      console.log(serials);
    },
    async update_ui_serials() {
      var serials = await window.electronAPI.getSerials();
      if (serials.length === undefined) {
        console.log("no serials fund");
        return;
      }

      /* add new com to list */
      for (var i = 0; i < serials.length; i++) {
        var incomConnectList = 0;
        for (var j = 0; j < this.comConnectList.length; j++) {
          if (serials[i].path == this.comConnectList[j].path) {
            incomConnectList = 1;
            break;
          }
        }
        if (incomConnectList == 0) {
          var incomParasList = 0;
          for (var j = 0; j < this.comParasList.length; j++) {
            if (this.comParasList[j].path == serials[i].path &&
              this.comParasList[j].name == serials[i].friendlyName) {

              var serials_item = {
                path: serials[i].path,
                name: serials[i].friendlyName,
                buadrate: this.comParasList[j].buadrate,
                databits: this.comParasList[j].databits,
                stopbits: this.comParasList[j].stopbits,
                checkBits: this.comParasList[j].checkBits,
                controlBits: this.comParasList[j].controlBits,
                timeOut: this.comParasList[j].timeOut,
                status: 0
              };
              this.comConnectList.push(serials_item);

              incomParasList = 1;
              break;
            }
          }
          if (incomParasList == 0) {
            var serials_item = {
              path: serials[i].path,
              name: serials[i].friendlyName,
              buadrate: '115200',
              databits: 8,
              stopbits: 1,
              checkBits: 'NONE',
              controlBits: 'NONE',
              timeOut: 0,
              status: 0
            };
            this.comConnectList.push(serials_item);
          }
        }
      }

      /* rm invalid com from list*/
      for (var i = 0; i < this.comConnectList.length; i++) {
        var valid = 0;
        for (var j = 0; j < serials.length; j++) {
          if (this.comConnectList[i].path == serials[j].path) {
            valid = 1;
            break;
          }
        }
        if (valid == 0) {
          this.comConnectList.splice(i, 1);
        }
      }
    },
    async change_serial_status(item) {
      await window.electronAPI.setSerials(item);
    },
    async change_net_status(item) {
      await window.electronAPI.setNets(item);
    },
    async send_messages(message) {
      var result = await window.electronAPI.setSerials(message);
      console.log("send_messages:" + result);
    },
    async open_url_version() {
      await window.electronAPI.openUrl("https://gitee.com/sangzeyao/mcom");

    },
    async open_url_document() {
      await window.electronAPI.openUrl("https://gitee.com/sangzeyao/mcom");
    }
  },
  beforeDestroy() {
    if (this.timerUpdateSerials) {
      clearInterval(this.timerUpdateSerials);
    }
    if (this.timerUpdateConfigs) {
      clearInterval(this.timerUpdateConfigs);
    }
  }
}
</script>

<style>
.drag-part {
  -webkit-app-region: drag;
}

.no-drag-part {
  -webkit-app-region: no-drag;
}
</style>